/**
 * 命名 首字母大写 驼峰
 */

import dayjs from 'dayjs'
import { useUserStore } from '../store/modules/user'
import { asyncRoutes, resetRouter } from '../router'
import { handleActivePath } from './routes'
import { useTabsStore } from '../store/modules/tabs'

// 正则校验
export const RegTest = (value: any, type: string, info = '') => {
  let reg: any

  // 数字
  if (type == 'number') {
    reg = /^[0-9]+.?[0-9]*/
    return reg.test(value)
  }
}

// 加密方式
export const Encryption = (value: string | number, type: string, info = '') => {
  /**
   * @param value 值
   * @param type  类型
   * @param info  【用于打印信息】
   */
  const encry = `${value}`
  // 手机号码
  if (type == 'phone') return encry.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2')
  // 银行卡
  if (type == 'bank_number')
    return encry.replace(/(?<=\d{4})\d+(?=\d{4})/, ' **** **** ')
}

// 字符串分割
export const StrSplit = (str: string, mark: string, index: number) => {
  /*
   * str字符串 ”aaa：bbb：ccc“
   * mark分割符号 ：
   * index 下标
   * */
  const arr = str.split(mark)
  return arr[index]
}

// 数组对象降维
export const ArrayFlat = (arr: any, children = 'children') => {
  /**
   * arr 数组
   * children 子键名 默认 为children
   */
  if (!arr.length) return []
  if (arr instanceof Array) {
    for (let i = 0; i < arr.length; i++) {
      if (arr[i][children] && arr[i][children].length > 0) {
        arr = arr.slice(0, i + 1).concat(arr[i][children], arr.slice(i + 1))
      }
    }
  }
  return arr
}
// 数组字符串降维
export const ArrayStrFlat = (arr: any) => {
  /**
   * arr 数组 [[1, 2], [3, 4], [5, 6]];
   */

  return arr.reduce((acc: string | any[], cur: any) => {
    return acc.concat(cur);
  }, []);
}
// 数字逗号分割 123,456.7894
export const DigitSplit = (value: any, type = 'money', decimal = 2) => {
  /*
   * value 值
   * type 类型 money 金额 其他数字
   * decimal 保留几位小数 默认两位
   * */

  if (type == 'money' && !value) return '0.0000'
  if (type != 'money' && !value) return 0.0

  const str = value.toString()
  const int = StrSplit(str, '.', 0)
  let float = StrSplit(str, '.', 1)
  let floatafter = '.00'
  if (decimal == 4) {
    floatafter = '.0000'
  }

  // 0.6 ==> 0.60
  if (String(float).length == 1) {
    float = float + '0'
  }
  const reg = /(\d)(?=(?:\d{3})+$)/g
  const newInt = int.toString().replace(reg, '$1,')
  return float
    ? `${newInt}.${float}`
    : `${newInt}${type == 'money' ? floatafter : ''}`
}

// 时间格式化
export const timeDayjs = (va: any, format = 'YYYY-MM-DD HH:mm:ss') => {
  if (!va) return '--'

  // 时间默认
  if (va == '0000-00-00 00:00:00') return '--'
  if (va == '1970-01-01 00:00:00') return '--'

  const datetimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/
  if (datetimeRegex.test(va)) {
    return va
  } else {
    const date = new Date(Number(va))
    const year = date.getFullYear()
    const month = (date.getMonth() + 1).toString().padStart(2, '0')
    const day = date.getDate().toString().padStart(2, '0')
    const hours = date.getHours().toString().padStart(2, '0')
    const minutes = date.getMinutes().toString().padStart(2, '0')
    const seconds = date.getSeconds().toString().padStart(2, '0')

    const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
    return formattedDate
  }
}
// 三位 ①逗号 123,4.123
export const ToThousands = (num: any) => {
  return num.toString().replace(/\d+/, function (n: any) {
    return n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
  })
}
// 数据强制保留小数 [默认两位]
export const ToDecimal = (x: any, num = 2) => {
  if (num == 0) return Number(x)

  // 倍数
  let multiple = Math.pow(100, num)

  let f = parseFloat(x)
  if (isNaN(f)) {
    return false
  }
  f = Math.round(x * multiple) / multiple
  let s = f.toString()
  let rs = s.indexOf('.')
  if (rs < 0) {
    rs = s.length
    s += '.'
  }
  while (s.length <= rs + num) {
    s += '0'
  }
  return s
}

/**
 * 'null' 'undefined' 'false' '' 'NaN' '{}' '[]'
 */
export const IsValueHave = (value: any) => {
  const _value = JSON.stringify(value)

  if (
    _value == '""' ||
    _value == 'null' ||
    _value == null ||
    _value == 'undefined' ||
    _value == undefined ||
    _value == 'false' ||
    _value == 'NaN' ||
    _value == '{}' ||
    _value == '[]'
  )
    return false

  return true
}

// 金钱格式化
export const MoneyFormat = (value: string | number, post = 4) => {
  if (!IsValueHave(value)) return '--'

  const money = ToDecimal(value, post)
  return ToThousands(money)
}
// 数量格式化
export const NumberFormat = (value: string | number, post = 2) => {
  if (!IsValueHave(value)) return '--'

  const number = ToDecimal(value, post)
  return ToThousands(number)
}
// 日期格式化
export const DateFormat = (
  value: string | number,
  format = 'YYYY-MM-DD HH:mm:ss'
) => {
  if (!IsValueHave(value)) return '--'

  return dayjs(value).format(format)
}
// 字段级格式化
export const FieldFormat = (value: string | number, type = '', ratio = 2) => {
  if (!IsValueHave(value)) return '--'

  if (value == 0) value = value.toString()
  if (
    value == '' ||
    value == ' ' ||
    value == null ||
    value == undefined ||
    value == '{}' ||
    value == '[]'
  )
    return '--'

  // 默认
  if (!type) return value

  // 是/否
  if (type == 'boolean') {
    if (value == 0 || value == '0') return '否'
    if (value == 1 || value == '1') return '是'
  }

  // 数字
  if (type == 'number') return NumberFormat(value, 0)
  // 金钱 默认保留两位 [money_eye 加密]
  if (type == 'money' || type == 'money_eye') return MoneyFormat(value, ratio)
  // 比率
  if (type == 'ratio') return value ? `${value}%` : '0.00%'
  // 时间
  if (type == 'time') return timeDayjs(value)
  //  手机号码
  if (type == 'phone') return Encryption(value, type)
  //  手机号码
  if (type == 'bank_number') return Encryption(value, type)
}

//@return 00:00:00 预计上传时间
export const EstimatedTime = (times = 0) => {
  if (typeof times === 'number') {
    if (times <= 0) {
      return '00:00:00'
    } else {
      const hh: number = parseInt(String(times / 3600)) //小时
      const shh: number = times - hh * 3600
      const ii: number = parseInt(String(shh / 60))
      const ss: number = shh - ii * 60
      return `${ii}分${ss}秒`
    }
  } else {
    return '00:00:00'
  }
}

// 默认 起始 00:00:00 结束 23:59:59
export const DefaultTime: [Date, Date] = [
  new Date(2000, 1, 1, 0, 0, 0),
  new Date(2000, 2, 1, 23, 59, 59),
]
// 默认
export const TimeFormat = 'YYYY-MM-DD HH:mm:ss'

// 排除空值
export const ExcludeEmpty = async (value: any) => {
  let _value: any = []

  const str = await value[value.length - 1].toString()

  if (!str) {
    _value = ['']
  } else {
    _value = value.filter((item: any) => {
      return RegTest(item, 'number')
    })
  }
  return _value
}

// 验证码随机数
export const RandomCode = (codeLength: number) => {
  function random(min: number, max: number) {
    return Math.floor(Math.random() * (max - min)) + min
  }

  // codeLength 为随机字符长度
  let randomCode: any =
    'abcdefghijklmnopqrstuvwxyz' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
  randomCode = randomCode.split('')
  var res_code = ''
  while (res_code.length < codeLength) {
    res_code += randomCode[random(0, randomCode.length)]
  }
  // 返回随机字符集
  return res_code
}

// 整数随机数 可以充当随机 编码/id
export const MathRandom = Math.floor(Math.random() * 1000000000000)

// 数组对象去重
export const FilterRepeat = (arr: any, key: string, arrType = 'obj') => {
  if (!arr.length) return []
  // 数组对象
  if (arrType == 'obj') {
    const res = new Map()
    return arr.filter(
      (item: any) => !res.has(item[key]) && res.set(item[key], 1)
    )
  }
  // 数组字符串
  if (arrType == 'str') {
    const result: any = arr.reduce((prev: any, item: any) => {
      if (!prev.includes(item)) {
        prev.push(item)
      }
      return prev
    }, [])
    return result
  }
}

// 转字符串
export const StrShift = (value: any) => {
  return value.toString()
}

// 根据code 返回 地址name
export const SeekAddressName = (code: any[], arrdessOptions: any[]) => {
  // 例如 code [10001,1002,1003]

  const addressName: any = []

  // 降维
  const array = ArrayFlat(arrdessOptions)

  // 通过编码查找对象名称
  for (let index = 0; index < array.length; index++) {
    const element = array[index]
    if (element.code == code[0]) addressName[0] = element.name
    if (element.code == code[1]) addressName[1] = element.name
    if (element.code == code[2]) addressName[2] = element.name
  }

  return addressName
}

// 遍历数组返回某个字段的集合
export const ReturnReduce = (list: any[], key = '') => {
  return list.reduce((pre, el, index) => {
    pre.push(el[key])
    return pre
  }, [])
}

// 文件下载【通过长链接下载】
export const DownloadFile = (url: string, fileName: string) => {
  // 创建XMLHttpRequest对象
  var xhr = new XMLHttpRequest()

  xhr.open('GET', url, true)

  xhr.responseType = 'blob'

  // 注册事件监听函数
  xhr.onload = function () {
    if (xhr.status === 200) {
      // 成功获取文件
      var blob = xhr.response

      // 使用FileSaver.js库实现文件下载
      window.saveAs(blob, fileName)
    } else {
      // 获取文件失败
      console.log('Failed to download file')
    }
  }

  // 发送请求
  xhr.send()
}

// 根据月判定有多少天的方法
export const GetMonthLength = (date: any) => {
  const d: any = new Date(date)

  // 将日期设置为下月一号

  d.setMonth(d.getMonth() + 1)

  // d.setDate(1)

  // 获取本月最后一天

  d.setDate(d.getDate() - 1)

  return d.getDate()
}

// 数值展示 可加币别
export const YAxisDormatCurrency = (v: any, str = '') => {
  v = v.toString()
  if (v >= 100000000000) {
    return str + v.substring(0, 5) / 10 + '亿'
  } else if (v >= 10000000000) {
    return str + v.substring(0, 4) / 10 + '亿'
  } else if (v >= 1000000000) {
    return str + v.substring(0, 3) / 10 + '亿'
  } else if (v >= 100000000) {
    return str + v.substring(0, 2) / 10 + '亿'
  } else if (v >= 10000000) {
    return str + v.substring(0, 4) + 'w'
  } else if (v >= 1000000) {
    return str + v.substring(0, 3) + 'w'
  } else if (v >= 100000) {
    return str + v.substring(0, 2) + 'w'
  } else if (v >= 10000) {
    return str + v.substring(0, 2) / 10 + 'w'
  } else if (v >= 1000) {
    return str + v
  } else {
    return str + v
  }
}

// 数组等分 二维
export const ArraySliceLength = (array: any, subGroupLength: number) => {
  // array 代表一个数组
  // subGroupLength 代表数组里面的数组的length值
  let index = 0
  let newArray = []
  while (index < array.length) {
    newArray.push(array.slice(index, (index += subGroupLength)))
  }
  return newArray
}

/***
 * @校验用户权限
 * @param name 当前页面路由 name
 */
export const CheckUserAuth = (name: string) => {
  const userStore: any = useUserStore()
  const { isMaster, authMenu } = userStore

  /*
    若当前用户是主用户 【全权限】
  */
  if (isMaster) return true
  // .all 全部权限 .readonly 只读
  return authMenu.indexOf(name + '.all') > -1
}
/***
 * @校验路由权限
 * @param menu 权限菜单 登录获取
 */
export const CheckRouterAuth = async (menu:any) => {
  // 本地路由
  const routerList:any = asyncRoutes
  // 权限菜单
  const userStore: any = useUserStore()
  const { authMenu } = userStore
  const { is_master } = BaseUserInfo()
  let menuAuth = menu ? menu : authMenu

  // 主应用 默认获取所有权限
  if (is_master) {
    menuAuth = ArrayOneValue(
      ArrayFlat(routerList, 'children'),
      'authName'
    )
  }

  // 路由递归遍历
  const routerDiff = (array: [], menuAuth:any)=>{
    for (let i = 0; i < array.length; i++) {
      const row:any = array[i];

      if (menuAuth.indexOf(row.name + '.all') > -1 || menuAuth.indexOf(row.name + '.readonly') > -1) {
        row.meta.authShow = true
      } else{
        row.meta.authShow = false
      }

      if (row.children && row.children.length) {
        routerDiff(row.children, menuAuth)
      }
    }
  }

  await routerDiff(routerList, menuAuth)

  return routerList
}

// 返回数组对象某键 形成新数组
export const ArrayOneValue = (_array: any[], key: string) => {
  return _array.map((x: any) => {
    return x[key]
  }) // 生成数组
}

// 基础用户信息【本地缓存】
export const BaseUserInfo = ()=>{
  const storageJSON: any = localStorage.getItem('userInfo')
  const userInfo = JSON.parse(storageJSON)
  return userInfo
}

/**
 * 关闭当前页签
 * @param initPath 当前路径
 * @param route 路由实例
 * @param router 路由跳转
 */
export const CloseNowTabs = (initPath: string, route:any, router:any)=>{

  const tabStore = useTabsStore()
  const { getVisitedRoutes: visitedRoutes } = storeToRefs(tabStore)
  const { delVisitedRoute } = tabStore

  const handleTabRemove = async (rawPath: string) => {
    if (isActive(rawPath)) await toLastTab()
    await delVisitedRoute(rawPath)
  }

  const toLastTab = async () => {
    const latestView = visitedRoutes.value.filter((item) => item.path !== handleActivePath(route, true)).slice(-1)[0]
    if (latestView) await router.push(latestView)
    else await router.push('/')
  }

  const isActive = (path: any) => {
    return path === handleActivePath(route, true)
  }

  handleTabRemove(initPath)
}
